`timescale 1ns / 1ps
/*
Time:2024.10.18
Author:祝文卓
Usage：串口发送模块
Parameters： clk时钟  rst复位  start开始标志位 tx发送的电平 busy发送标志位
Value of return：None
Time of modification：2024.10.7
*/
module UART_T(
    input wire i_clk,
    input wire i_rst,
    input wire i_tx_start,                         //开始发送的信号
    input wire [7:0] i_tx_data,                    //要发送的数据
    output reg o_tx,                               //串口发送输出
    output reg o_tx_busy                           //发送忙碌
    );

    parameter CLK_FREQ  = 50000000;              //时钟频率
    parameter BAUD_RATE = 9600;

    localparam BIT_PERIOD=CLK_FREQ / BAUD_RATE ; //发送一位需要的时钟周期

    reg [3:0] bit_index = 0;  // 当前位索引
    reg [15:0] clk_count = 0; // 时钟计数器
    reg [7:0] tx_buffer;      // 待发送的数据缓冲   

    always @(posedge i_clk or negedge i_rst) begin
        if(!i_rst)begin
            o_tx<=1'b1;       //空闲的时候tx是高电平
            o_tx_busy<=0;     //不忙
            bit_index<=0;
            clk_count<=0;
        end else if (i_tx_start && ! o_tx_busy) begin       //发送使能，同时空闲状态
            o_tx_busy <= 1;
            tx_buffer<=i_tx_data;  //将数据传入缓冲器
            bit_index<=0;
            clk_count<=0;
            o_tx<=0;                //起始位是低电平

        end else if (o_tx_busy) begin //传输的时候，busy为高电平
            if (clk_count<BIT_PERIOD-1) begin   //说明没有传输完一位数据
                clk_count <= clk_count + 1;
            end else begin
                clk_count<=0;
                bit_index <= bit_index + 1;     //传输完了一位数据

                if(bit_index<8)begin
                    o_tx <= tx_buffer[bit_index];   //发送数据位
                end else if (bit_index==8) begin    //发送完一字节的数据
                    o_tx<=1;  //tx发送停止位，此时一字节数据发送完
                end else begin  //一字节数据传输完
                    o_tx_busy <= 0; // 传输完成
                    o_tx<=1;        // 保持高电平
                end
            end 
        end
   end
endmodule


